package Read;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;

import Definitions.ContentClass;
import Definitions.GraphClass;
import Definitions.NodeClass;
import FeatureSelection.FeatureSelectionDataClass;
import FeatureSelection.FeatureSelectionManagerClass;
import Global.ClassIdentificationClass;
import Global.ConstantVariable;
import Global.GlobalClass;
import Sampling.SamplingAbstractClass;

/*****************************************************************
* Name : Reader
* Aim : This class is responsible of the read operations from the external files. *
*****************************************************************/
public class ReaderClass
{
	public ReaderClass() 
	{
		// TODO Auto-generated constructor stub
	}
	
	/*****************************************************************
	* Name : Read
	* Aim : This method aims to read from the given file and fill in the graph with the related data.*
	* Inputs : String fileNameContent : the content file 
	* 			String fileNameCites : the neighborhood file
	* 			String splitchar : the char value that will be used to split between contents and neighbors
	* while reading from file
	* 			ArrayList <Integer> useContentList : 
	* 			Global global : Global variables
	* 			Graph graph : Graph
	* Outputs :  - *
	* Data Structures : *
	* Algorithms : Firstly it reads from the content file and fill in the graph and nodes' contents, then this method reads from 
	* the cites file and fill the neighbors of each node respectively *
	*****************************************************************/
	 
	public void Read(String fileNameContent, String fileNameCites,String splitchar ,GraphClass graph, GlobalClass global)
	{
		 try
		 {
			  int edgeType = 0;
			  int contentType = 0;
	    	  FileInputStream fstream = new FileInputStream(fileNameContent);
	    	  DataInputStream contentFile = new DataInputStream(fstream); 					// getting input file
	    	  BufferedReader br = new BufferedReader(new InputStreamReader(contentFile));	// setting the reader class for the input file
	    	  String strLine; 

	    	  FeatureSelectionDataClass featureSelectionData = null;
	    	  
	    	  if(ConstantVariable.ExecutionParameters.useFeatureSelectionFromInputFiles)
	    	  {
	    		  featureSelectionData = FeatureSelectionManagerClass.getSelectedFeaturesFromFile(contentType);
	    	  }
	    	  
	    	  // Reading from File Line By Line   than splitting the line <paper_id> <word_attributes>+ <class_label>
	    	  int nodeOrder = 0;
	    	  while ((strLine = br.readLine()) != null)
	    	  {
	    		  String[] words = strLine.split("	");  				// Splitting words with " "
	    		  NodeClass node = new NodeClass (graph);
	    		  node.setId(words[0]);									// Setting the node id
	    		  ContentClass content = new ContentClass();
	    		  double sum=0;
	    		  double atribute;
	    		  
	    		  for (int k= 1 ; k<words.length -1 ;k++)  				// Filling in the attribute list of the content
	    		  {  
	    			  if(featureSelectionData==null || (featureSelectionData!=null && featureSelectionData.selectThisFeatureOrNot(k-1)))
	    			  {
	    				  atribute= Integer.parseInt(words[k]) ;
	    				  content.getAttributeList().add(atribute) ;
	    				  sum +=  atribute*atribute;
	    			  }
	    		  }	    		   
	    		  content.setLenght((double)Math.sqrt(sum));
	    		  content.setId(contentType);
	    		  node.getContentList().add(content);					// Adding the content to related node
	    		  node.setOrder(nodeOrder++);
		        	
	    		  String className= words[words.length -1];
	    		  boolean isFoundBefore= false;
	    		  
	    		  for(int i = 0; !isFoundBefore && i< global.classList.size(); i++)		// Checking whether a node of recent class is found and added to classList before or not
	    		  {
	    			  if(global.classList.get(i).getName().compareTo(className) == 0)
	    			  {	
	    				  isFoundBefore = true;
	    				  node.setClassOrder(i);
	    			  }
	    		  }
		        	
	    		  if(isFoundBefore == false)							// If this class is not found before, add it to global classList
	    		  {
	    			  ClassIdentificationClass e = new ClassIdentificationClass();
			          e.setName(className);
			       	  e.setId(global.classList.size());
			       	  global.classList.add(e);
		        	  node.setClassOrder(global.classList.size()-1);
		        	  global.classSize = global.classList.size();		        	  
	    		  }
	    		  graph.getDataSet().add(node);
	    		  
	    	  }
	    	  contentFile.close();
		    		
	    	  //Filling the global classList array with ratios of each class and initialize the edge list for each node in the dataset
	    	  global.findRatios(graph);
	    	  graph.InitializeEdgeList(edgeType);

	    	  //Reading the cites file which contains the neighborhood relationship between nodes
	    	  FileInputStream fstreamCite = new FileInputStream(fileNameCites);
	    	  DataInputStream citesFile = new DataInputStream(fstreamCite);
	    	  BufferedReader brCite = new BufferedReader(new InputStreamReader(citesFile));
	    	  String strLineCite;
	    	  
	    	  //int sayac=0;
	    	  //Read from File Line By Line
	    	  while ((strLineCite = brCite.readLine()) != null)
	    	  {
	    		  String[] words = strLineCite.split( splitchar);
	    		  if(words[0].compareTo(words[1])!=0)
	    		  {
	    			  graph.addNeighbourNode(words[0], words[1],0, global);		//Add the neighbors of the each related nodes
	    			  global.linksChecker.addToTheLinksList(words[0], words[1]);	    			  
	    		  }
	    		  global.linksChecker.increaseNumberOfLinksInTheFile();
	    		  if(words[0].equals(words[1]))
	    			  global.linksChecker.increaseNumberOfSelfCitations();
	    		  /*sayac++;
	    		  if(sayac%1000==0)
	    			  System.out.println("sayac"+sayac);*/
	    	  }
	    	  citesFile.close();
	    	  
	    	  
	    	  double temp=(double)0;
    		  for(int i=0; i< graph.getDataSet().size(); i++)
    		  {
    			  for(int j=0; j<global.classList.size(); j++)
    				  graph.getDataSet().get(i).getContentList().get(contentType).getLabelRatiosOfContents().add( temp);
    		  }
    		  for(int i=0; i< graph.getDataSet().size(); i++)
    		  {
    			  for(int j=0; j<global.classList.size(); j++)
    				  graph.getDataSet().get(i).getEdgeList().get(edgeType).getLabelRatiosOfLinks().add(temp);
    		  }
		 }
		 catch (Exception e)//Catch exception if any
		 {       
			 System.err.println("Error: " + e.getMessage());
		 }    		
	}
	
	public void Read(String fileNameContent, String fileNameCites, String splitchar ,GraphClass graph, GlobalClass global, int a)
	{
		 try
		 {
			  System.out.println(" Reading...");
			  int edgeType = 0;
			  int contentType = 0;
	    	  FileInputStream fstream = new FileInputStream(fileNameContent);
	    	  DataInputStream contentFile = new DataInputStream(fstream); 					// getting input file
	    	  BufferedReader br = new BufferedReader(new InputStreamReader(contentFile));	// setting the reader class for the input file
	    	  String strLine; 
	    	  
	    	  // Reading from File Line By Line   than splitting the line <paper_id> <word_attributes>+ <class_label>
	    	  int nodeOrder = 0;
	    	  while ((strLine = br.readLine()) != null)
	    	  {
	    		  
	    		  String[] words = strLine.split(" ");  				// Splitting words with " "
	    		  NodeClass node = new NodeClass(graph);
	    		  String className= words[0];	
	    		  ContentClass content = new ContentClass();
	    		  double sum=0;
	    		  for (int k= 1 ; k<words.length  ;k++)  				// Filling in the attribute list of the content
	    		  {  
	    			  double atribute= Integer.parseInt(words[k])-1;
	    			  content.getAttributeList().add(atribute) ;
	    			  sum +=  atribute*atribute;
	    		  }	    		   
	    		  content.setLenght((double)Math.sqrt(sum));
	    		  content.setId(contentType);
	    		  node.getContentList().add(content);					// Adding the content to related node
	    		  node.setOrder(nodeOrder++);
	    		  node.setId(Integer.toString(nodeOrder));									// Setting the node id	
	    		  boolean isFoundBefore= false;
	    		  
	    		  for(int i = 0; !isFoundBefore && i< global.classList.size(); i++)		// Checking whether a node of recent class is found and added to classList before or not
	    		  {
	    			  if(global.classList.get(i).getName().compareTo(className) == 0)
	    			  {	
	    				  isFoundBefore = true;
	    				  node.setClassOrder(i);
	    			  }
	    		  }
		        	
	    		  if(isFoundBefore == false)							// If this class is not found before, add it to global classList
	    		  {
	    			  ClassIdentificationClass e = new ClassIdentificationClass();
			          e.setName(className);
			       	  e.setId(global.classList.size());
			       	  global.classList.add(e);
		        	  node.setClassOrder(global.classList.size()-1);
	    		  }
	    		  graph.getDataSet().add(node);
	    		  
	    	  }
	    	  contentFile.close();
		    		
	    	  //Filling the global classList array with ratios of each class and initialize the edge list for each node in the dataset
	    	  global.findRatios(graph);
	    	  graph.InitializeEdgeList(edgeType);

	    	  //Reading the cites file which contains the neighborhood relationship between nodes
	    	  FileInputStream fstreamCite = new FileInputStream(fileNameCites);
	    	  DataInputStream citesFile = new DataInputStream(fstreamCite);
	    	  BufferedReader brCite = new BufferedReader(new InputStreamReader(citesFile));
	    	  String strLineCite;
	    	  //Read from File Line By Line
	    	  while ((strLineCite = brCite.readLine()) != null)
	    	  {
	    		  String[] words = strLineCite.split( splitchar);
	    		  if(words[0].compareTo(words[1])!=0)
	    		  graph.addNeighbourNode(words[0], words[1],0, global);		//Add the neighbors of the each related nodes
	    	  }
	    	  citesFile.close();
	    	  
	    	  
	    	  double temp=(double)0;
    		  for(int i=0; i< graph.getDataSet().size(); i++)
    		  {
    			  for(int j=0; j<global.classList.size(); j++)
    				  graph.getDataSet().get(i).getContentList().get(contentType).getLabelRatiosOfContents().add( temp);
    		  }
    		  for(int i=0; i< graph.getDataSet().size(); i++)
    		  {
    			  for(int j=0; j<global.classList.size(); j++)
    				  graph.getDataSet().get(i).getEdgeList().get(edgeType).getLabelRatiosOfLinks().add(temp);
    		  }
		 }
		 catch (Exception e)//Catch exception if any
		 {       
			 System.err.println("Error: " + e.getMessage());
		 }    		

	}
	public void Read(String fileNameFeatures, String splitchar ,GraphClass graph, GlobalClass global)
	{
		 try
		 {
	    	  FileInputStream fstream = new FileInputStream(fileNameFeatures);
	    	  DataInputStream features = new DataInputStream(fstream); 					// getting input file
	    	  BufferedReader br = new BufferedReader(new InputStreamReader(features));	// setting the reader class for the input file
	    	  String strLine; 
	    	  
	    	  // Reading from File Line By Line   than splitting the line <paper_id> <word_attributes>+ <class_label>
	    	  int nodeOrder = 0;
	    	  while ((strLine = br.readLine()) != null)
	    	  {
	    		  String[] words = strLine.split(" ");  				// Splitting words with " "
	    		  NodeClass node = new NodeClass(graph);
	    		  node.setId(words[0]);									// Setting the node id
	    		  node.setOrder(nodeOrder++);
	    		  String className= words[1];
	    		  boolean isFoundBefore= false;
	    		  
	    		  for(int i = 0; !isFoundBefore && i< global.classList.size(); i++)		// Checking whether a node of recent class is found and added to classList before or not
	    		  {
	    			  if(global.classList.get(i).getName().compareTo(className) == 0)
	    			  {	
	    				  isFoundBefore = true;
	    				  node.setClassOrder(i);
	    			  }
	    		  }
		        	
	    		  if(isFoundBefore == false)							// If this class is not found before, add it to global classList
	    		  {
	    			  ClassIdentificationClass e = new ClassIdentificationClass();
			          e.setName(className);
			       	  e.setId(global.classList.size());
			       	  global.classList.add(e);
		        	  node.setClassOrder(global.classList.size()-1);
	    		  }
	    		  graph.getDataSet().add(node);
	    		  
	    	  }
	    	  features.close();
		    		
		 }
		 catch (Exception e)//Catch exception if any
		 {       
			 System.err.println("Error: " + e.getMessage());
		 }    		
	}
	
	

	public void ReadContent(String fileNameContent, String splitchar ,GraphClass graph, GlobalClass global)
	{
		 try
		 {
			  
			  int contentType = 0;
	    	  FileInputStream fstream = new FileInputStream(fileNameContent);

	    	  DataInputStream contentFile = new DataInputStream(fstream); 					// getting input file
	    	  BufferedReader br = new BufferedReader(new InputStreamReader(contentFile));	// setting the reader class for the input file
	    	  String strLine; 
	    	  
	    	  // Reading from File Line By Line   than splitting the line <paper_id> <word_attributes>+ <class_label>
	    	 
	    	  while ((strLine = br.readLine()) != null)
	    	  {
	    		  String[] words = strLine.split("	");  				// Splitting words with " "
	    		  NodeClass node = new NodeClass(graph);
	    		  ContentClass content = new ContentClass();
	    		  double sum=0;
	    		  for (int k= 0 ; k<words.length  ;k++)  				// Filling in the attribute list of the content
	    		  {  
	    			  double atribute= Integer.parseInt(words[k]);
	    			  content.getAttributeList().add(atribute) ;
	    			  sum +=  atribute*atribute;
	    		  }	    		   
	    		  content.setLenght((double)Math.sqrt(sum));
	    		  content.setId(contentType);
	    		  node.getContentList().add(content);					// Adding the content to related node

	    	  }
	    	  contentFile.close();
		    		
	     }
		 catch (Exception e)//Catch exception if any
		 {       
			 System.err.println("Error: " + e.getMessage());
		 }    		
	}

	/*****************************************************************
	* Name : Read_FeatureSelection
	* Aim : This method aims to read from the given file and fill in the graph with the related data.*
	* Inputs : String fileNameContent : the content file 
	* 			String fileNameCites : the neighborhood file
	* 			String splitchar : the char value that will be used to split between contents and neighbors
	* 			while reading from file
	* 			ArrayList <Integer> useContentList : 
	* 			Global global : Global variables
	* 			Graph graph : Graph
	* Outputs :  - *
	* Data Structures : *
	* Algorithms : Firstly it reads from the content file and fill in the graph and nodes' contents, then this method reads from 
	* the cites file and fill the neighbors of each node respectively *
	*****************************************************************/
	public void Read_FeatureSelection(String fileNameContent, String fileNameCites,String splitchar , ArrayList <Integer> useContentList, GlobalClass global, GraphClass graph)
	{
		 try
		 {
			  int edgeType = 0;
			  int contentType = 0;
	    	  FileInputStream fstream = new FileInputStream(fileNameContent);

	    	  DataInputStream contentFile = new DataInputStream(fstream); 					// getting input file
	    	  BufferedReader br = new BufferedReader(new InputStreamReader(contentFile));	// setting the reader class for the input file
	    	  String strLine; 
	    	  
	    	  // Reading from File Line By Line   than splitting the line <paper_id> <word_attributes>+ <class_label>
	    	  int nodeOrder = 0;
	    	  while ((strLine = br.readLine()) != null)
	    	  {
	    		  String[] words = strLine.split("	");  				// Splitting words with " "
	    		  NodeClass node = new NodeClass(graph);
	    		  node.setId(Integer.toString(nodeOrder+1));									// Setting the node id
	    		  ContentClass content = new ContentClass();
	    		  double sum=0;


	    		  for (int k= 0 ; k<useContentList.size() ;k++)  				// Filling in the attribute list of the content
	    		  {
	    			  double atribute= Integer.parseInt(words[useContentList.get(k)+1]);
	    			  content.getAttributeList().add(atribute) ;
	    			  sum +=  atribute*atribute;
	    		  	 
	    		  }
	    			 	    			    		   
	    		  content.setLenght((double)Math.sqrt(sum));
	    		  content.setId(contentType);
	    		  node.getContentList().add(content);					// Adding the content to related node
	    		  node.setOrder(nodeOrder++);
		        	
	    		  String className= words[words.length -1];
	    		  boolean isFoundBefore= false;
	    		  
	    		  for(int i = 0; !isFoundBefore && i< global.classList.size(); i++)		// Checking whether a node of recent class is found and added to classList before or not
	    		  {
	    			  if(global.classList.get(i).getName().compareTo(className) == 0)
	    			  {	
	    				  isFoundBefore = true;
	    				  node.setClassOrder(i);
	    			  }
	    		  }
		        	
	    		  if(isFoundBefore == false)							// If this class is not found before, add it to global classList
	    		  {
	    			  ClassIdentificationClass e = new ClassIdentificationClass();
			          e.setName(className);
			       	  e.setId(global.classList.size());
			       	  global.classList.add(e);
		        	  node.setClassOrder(global.classList.size()-1);
	    		  }
	    		  graph.getDataSet().add(node);
	    		  
	    	  }
	    	  contentFile.close();
		    		
	    	  //Filling the global classList array with ratios of each class and initialize the edge list for each node in the dataset
	    	  global.findRatios(graph);
	    	  graph.InitializeEdgeList(edgeType);

	    	  //Reading the cites file which contains the neighborhood relationship between nodes
	    	  FileInputStream fstreamCite = new FileInputStream(fileNameCites);
	    	  DataInputStream citesFile = new DataInputStream(fstreamCite);
	    	  BufferedReader brCite = new BufferedReader(new InputStreamReader(citesFile));
	    	  String strLineCite;
	    	  //Read from File Line By Line
	    	  while ((strLineCite = brCite.readLine()) != null)
	    	  {
	    		  String[] words = strLineCite.split( splitchar);
	    		  if(words[0].compareTo(words[1])!=0)
	    		  graph.addNeighbourNode(words[0], words[1],0, global);		//Add the neighbors of the each related nodes
	    	  }
	    	  citesFile.close();
	    	  
	    	  
	    	  double temp=(double)0;
    		  for(int i=0; i< graph.getDataSet().size(); i++)
    		  {
    			  for(int j=0; j<global.classList.size(); j++)
    				  graph.getDataSet().get(i).getContentList().get(contentType).getLabelRatiosOfContents().add( temp);
    		  }
    		  for(int i=0; i< graph.getDataSet().size(); i++)
    		  {
    			  for(int j=0; j<global.classList.size(); j++)
    				  graph.getDataSet().get(i).getEdgeList().get(edgeType).getLabelRatiosOfLinks().add(temp);
    		  }
		 }
		 catch (Exception e)//Catch exception if any
		 {       
			 System.err.println("Error: " + e.getMessage());
		 }    		
	}

	
	public void Read_FeatureSelection(String fileNameContent, String fileNameCites,String splitchar , ArrayList <Integer> useContentList, GlobalClass global, GraphClass graph, int f, SamplingAbstractClass currentSampling)
	{
		 try
		 {
			  int edgeType = 0;
			  int contentType = 0;
	    	  FileInputStream fstream = new FileInputStream("WebKBdata.data");

	    	  
	    	  ArrayList<String> listOfNodeID =new ArrayList<String>() ;
	    	  FileInputStream fstreamN = new FileInputStream("WebKBnodes.data");
	    	  DataInputStream cites = new DataInputStream(fstreamN);
	    	  BufferedReader br = new BufferedReader(new InputStreamReader(cites));
	    	  
	    	  String strLine;
	    	  //Read from File Line By Line

	    	  while ((strLine = br.readLine()) != null)
	    	  {
	    		  
	    		  String[] words = strLine.split(" ");
	    		  for(int i=0; i<words.length; i++)
	    			  listOfNodeID.add(words[i]);
	    		  
	    	  }
	    	  cites.close();
	    	  
	    	  
	    	  DataInputStream contentFile = new DataInputStream(fstream); 					// getting input file
	    	  br = new BufferedReader(new InputStreamReader(contentFile));	// setting the reader class for the input file
	    	   	    	  
	    	  // Reading from File Line By Line   than splitting the line <paper_id> <word_attributes>+ <class_label>
	    	  int nodeOrder = 0;
	    	  while ((strLine = br.readLine()) != null)
	    	  {
	    		  System.out.println("nodeOrder" + nodeOrder);
	    		  String[] words = strLine.split("	");  				// Splitting words with " "
	    		  NodeClass node = new NodeClass(graph);
	    		  node.setId(listOfNodeID.get(nodeOrder));									// Setting the node id
	    		  ContentClass content = new ContentClass();
	    		  double sum=0;
 
    			  
	    		  for (int k= 0 ; k<useContentList.size() ;k++)  				// Filling in the attribute list of the content
	    		  {
	    			  
	    			  double atribute= Integer.parseInt(words[useContentList.get(k)+1]);
	    			  content.getAttributeList().add(atribute) ;
	    			  sum +=  atribute*atribute;
	    		  	 
	    		  }
	    		  
	    		  content.setLenght((double)Math.sqrt(sum));
	    		  content.setId(contentType);
	    		  node.getContentList().add(content);					// Adding the content to related node
	    		  node.setOrder(nodeOrder++);
	    		  
	    		  graph.getDataSet().add(node);	
	    		  
	    	  }
	    	  contentFile.close();
		    		
	    	  
	    	  
	    	  FileInputStream fstreamTarget = new FileInputStream("WebKBtarget.data");
	    	  DataInputStream targetFile = new DataInputStream(fstreamTarget);
	    	  BufferedReader brTarget = new BufferedReader(new InputStreamReader(targetFile));
	    	  String strLineTarget;
	    	  int ClassOrder;
	    	  int order=0;
	    	
	    	  
	    	  while ((strLineTarget = brTarget.readLine()) != null)
	    	  {
	    		    
	    		  String className= strLine;
	    		  boolean isFoundBefore= false;
	    		  
	    		  String[] words = strLineTarget.split(" ");
	    		  for(int k=0; k< words.length; k++)
	    		  {  
	    			  className= words[k];
	    			  for(int i = 0; !isFoundBefore && i< global.classList.size(); i++)		// Checking whether a node of recent class is found and added to classList before or not
	    			  {
	    				  if(global.classList.get(i).getName().compareTo(className) == 0)
	    				  {		
	    					  isFoundBefore = true;
	    					  ClassOrder=i;
	    					  currentSampling.setClassLabelEstimated(graph.getDataSet().get(order), ClassOrder);
	    				  }
	    			  }
		        	
	    			  if(isFoundBefore == false)							// If this class is not found before, add it to global classList
	    			  {
	    				  ClassIdentificationClass e = new ClassIdentificationClass();
	    				  e.setName(className);
	    				  e.setId(global.classList.size());
	    				  global.classList.add(e);
	    				  graph.getDataSet().get(order).setClassOrder(global.classList.size()-1);
	    			  }
	    			  order++;
	    		  }
	    	  }

	    	  targetFile.close();
	    	  
	    	  
	    	  //Filling the global classList array with ratios of each class and initialize the edge list for each node in the dataset
	    	  global.findRatios(graph);
	    	  graph.InitializeEdgeList(edgeType);
	    	  
	    	  //Reading the cites file which contains the neighborhood relationship between nodes
	    	  FileInputStream fstreamCite = new FileInputStream("webKBCoCites.data");
	    	  DataInputStream citesFile = new DataInputStream(fstreamCite);
	    	  BufferedReader brCite = new BufferedReader(new InputStreamReader(citesFile));
	    	  String strLineCite;
	    	  //Read from File Line By Line
	    	  graph.print(edgeType);
	    	  int k=0;
	    	  while ((strLineCite = brCite.readLine()) != null)
	    	  {
	    		  String[] words = strLineCite.split(splitchar);
	    		  for(int i=0; i<words.length; i++)
	    		  if(words[k].compareTo(words[k+1])!=0)
	    		    graph.addNeighbourNode(words[0], words[1],0, global);		//Add the neighbors of the each related nodes
	    		  
	    	  }
	    	  citesFile.close();
    		  

	    	  
	    	  double temp=(double)0;
    		  for(int i=0; i< graph.getDataSet().size(); i++)
    		  {
    			  for(int j=0; j<global.classList.size(); j++)
    				  graph.getDataSet().get(i).getContentList().get(contentType).getLabelRatiosOfContents().add( temp);
    		  }
    		  for(int i=0; i< graph.getDataSet().size(); i++)
    		  {
    			  for(int j=0; j<global.classList.size(); j++)
    				  graph.getDataSet().get(i).getEdgeList().get(edgeType).getLabelRatiosOfLinks().add(temp);
    		  }
    		  
    		  
		 }
		 catch (Exception e)//Catch exception if any
		 {       
			 System.err.println("Error: " + e.getMessage());
		 }    		
	}
	
}
